package com.halfsword.creativecraft.modules;

import net.minecraft.nbt.CompoundTag;

/**
 * 分阶段蒸汽机制系统
 * 模拟蒸汽机的预热、平衡和冷却阶段，提供扭矩输出
 */
public class StagedSteamMechanism {

    public enum Stage {
        IDLE(0, "idle"),       // 闲置状态（初始状态）
        RISING(1, "rising"),   // 缓慢上升
        BALANCED(2, "balanced"), // 保持平衡
        DECLINING(3, "declining"); // 快速下降

        private final int id;
        private final String name;

        Stage(int id, String name) {
            this.id = id;
            this.name = name;
        }

        public int getId() {
            return id;
        }

        public String getName() {
            return name;
        }

        /**
         * 根据ID获取阶段枚举
         * @param id 阶段ID
         * @return 对应的阶段枚举，如果找不到则返回IDLE
         */
        public static Stage fromId(int id) {
            for (Stage stage : values()) {
                if (stage.id == id) {
                    return stage;
                }
            }
            return IDLE;
        }
    }

    // 当前系统状态
    private Stage currentStage = Stage.IDLE;
    private double currentTorque = 0.0; // 当前扭矩值（N·m）

    // 资源状态
    private int waterLevel = 0; // 当前水位（mB）
    private int fuelLevel = 0;  // 当前燃料量

    // 系统参数
    private final double maxTorque;
    private final double risingRate;
    private final double decliningRate;
    private final int waterConsumption;
    private final int fuelConsumption;
    private final int minWater;
    private final int minFuel;

    // 状态标志
    private boolean isEnabled = true;
    private boolean isDirty = false;

    /**
     * 构造函数
     * @param maxTorque 最大扭矩值
     * @param risingRate 上升速率（每tick增加的扭矩）
     * @param decliningRate 下降速率（每tick减少的扭矩）
     * @param waterConsumption 水消耗率（每tick消耗的水量）
     * @param fuelConsumption 燃料消耗率（每tick消耗的燃料量）
     * @param minWater 最小启动水量
     * @param minFuel 最小启动燃料量
     */
    public StagedSteamMechanism(double maxTorque, double risingRate, double decliningRate,
                                int waterConsumption, int fuelConsumption,
                                int minWater, int minFuel) {
        this.maxTorque = maxTorque;
        this.risingRate = risingRate;
        this.decliningRate = decliningRate;
        this.waterConsumption = waterConsumption;
        this.fuelConsumption = fuelConsumption;
        this.minWater = minWater;
        this.minFuel = minFuel;
    }

    /**
     * 每tick更新系统状态
     */
    public void tick() {
        if (!isEnabled) {
            return;
        }

        Stage previousStage = currentStage;

        switch (currentStage) {
            case IDLE:
                // 检查是否满足启动条件
                if (canStart()) {
                    transitionTo(Stage.RISING);
                }
                break;

            case RISING:
                // 扭矩上升
                currentTorque = Math.min(maxTorque, currentTorque + risingRate);

                // 达到最大扭矩时进入平衡状态
                if (currentTorque >= maxTorque) {
                    transitionTo(Stage.BALANCED);
                }
                break;

            case BALANCED:
                // 消耗资源
                consumeResources();

                // 资源不足时进入下降状态
                if (!hasEnoughResources()) {
                    transitionTo(Stage.DECLINING);
                }
                break;

            case DECLINING:
                // 扭矩快速下降
                currentTorque = Math.max(0, currentTorque - decliningRate);

                // 扭矩归零时回到闲置状态
                if (currentTorque <= 0) {
                    transitionTo(Stage.IDLE);
                }
                break;
        }

        // 如果阶段发生变化，标记为脏数据
        if (previousStage != currentStage) {
            markDirty();
        }
    }

    /**
     * 检查是否满足启动条件
     * @return 是否满足启动条件
     */
    private boolean canStart() {
        return waterLevel >= minWater && fuelLevel >= minFuel;
    }

    /**
     * 消耗资源
     */
    private void consumeResources() {
        int waterToUse = Math.min(waterLevel, waterConsumption);
        int fuelToUse = Math.min(fuelLevel, fuelConsumption);

        waterLevel -= waterToUse;
        fuelLevel -= fuelToUse;

        // 如果实际消耗量小于预期消耗量，标记为脏数据
        if (waterToUse < waterConsumption || fuelToUse < fuelConsumption) {
            markDirty();
        }
    }

    /**
     * 检查是否有足够的资源
     * @return 是否有足够的资源
     */
    private boolean hasEnoughResources() {
        return waterLevel >= waterConsumption && fuelLevel >= fuelConsumption;
    }

    /**
     * 转换到新阶段
     * @param newStage 新阶段
     */
    private void transitionTo(Stage newStage) {
        if (currentStage != newStage) {
            currentStage = newStage;
            markDirty();

            // 阶段转换时的特殊处理
            onStageTransition(newStage);
        }
    }

    /**
     * 阶段转换时的回调
     * @param newStage 新阶段
     */
    protected void onStageTransition(Stage newStage) {
        // 子类可以重写此方法以添加阶段转换时的特殊逻辑
    }

    /**
     * 标记数据为脏（需要保存）
     */
    private void markDirty() {
        this.isDirty = true;
    }

    /**
     * 清除脏标记
     */
    public void clearDirty() {
        this.isDirty = false;
    }

    /**
     * 检查数据是否为脏（需要保存）
     * @return 数据是否为脏
     */
    public boolean isDirty() {
        return isDirty;
    }

    // ===== 系统操作接口 =====

    /**
     * 添加水
     * @param amount 要添加的水量
     * @return 实际添加的水量
     */
    public int addWater(int amount) {
        if (amount <= 0) {
            return 0;
        }

        int canAdd = Integer.MAX_VALUE - waterLevel;
        int actualAdd = Math.min(canAdd, amount);
        waterLevel += actualAdd;

        markDirty();
        return actualAdd;
    }

    /**
     * 添加燃料
     * @param amount 要添加的燃料量
     * @return 实际添加的燃料量
     */
    public int addFuel(int amount) {
        if (amount <= 0) {
            return 0;
        }

        int canAdd = Integer.MAX_VALUE - fuelLevel;
        int actualAdd = Math.min(canAdd, amount);
        fuelLevel += actualAdd;

        markDirty();
        return actualAdd;
    }

    /**
     * 设置水位
     * @param waterLevel 新的水位
     */
    public void setWaterLevel(int waterLevel) {
        if (this.waterLevel != waterLevel) {
            this.waterLevel = Math.max(0, waterLevel);
            markDirty();
        }
    }

    /**
     * 设置燃料水平
     * @param fuelLevel 新的燃料水平
     */
    public void setFuelLevel(int fuelLevel) {
        if (this.fuelLevel != fuelLevel) {
            this.fuelLevel = Math.max(0, fuelLevel);
            markDirty();
        }
    }

    /**
     * 启用系统
     */
    public void enable() {
        if (!isEnabled) {
            isEnabled = true;
            markDirty();
        }
    }

    /**
     * 禁用系统
     */
    public void disable() {
        if (isEnabled) {
            isEnabled = false;
            markDirty();
        }
    }

    /**
     * 检查系统是否启用
     * @return 系统是否启用
     */
    public boolean isEnabled() {
        return isEnabled;
    }

    /**
     * 重置系统到初始状态
     */
    public void reset() {
        currentStage = Stage.IDLE;
        currentTorque = 0.0;
        waterLevel = 0;
        fuelLevel = 0;
        markDirty();
    }

    // ===== 状态获取接口 =====

    /**
     * 获取最大扭矩
     * @return 最大扭矩
     */
    public double getMaxTorque() {
        return maxTorque;
    }

    /**
     * 获取当前扭矩
     * @return 当前扭矩
     */
    public double getCurrentTorque() {
        return currentTorque;
    }

    /**
     * 获取当前扭矩百分比
     * @return 当前扭矩百分比 (0.0 - 1.0)
     */
    public double getCurrentTorquePercent() {
        return maxTorque > 0 ? currentTorque / maxTorque : 0.0;
    }

    /**
     * 获取当前阶段
     * @return 当前阶段
     */
    public Stage getCurrentStage() {
        return currentStage;
    }

    /**
     * 获取当前水位
     * @return 当前水位
     */
    public int getWaterLevel() {
        return waterLevel;
    }

    /**
     * 获取当前燃料水平
     * @return 当前燃料水平
     */
    public int getFuelLevel() {
        return fuelLevel;
    }

    /**
     * 获取水消耗率
     * @return 水消耗率
     */
    public int getWaterConsumption() {
        return waterConsumption;
    }

    /**
     * 获取燃料消耗率
     * @return 燃料消耗率
     */
    public int getFuelConsumption() {
        return fuelConsumption;
    }

    /**
     * 获取最小启动水量
     * @return 最小启动水量
     */
    public int getMinWater() {
        return minWater;
    }

    /**
     * 获取最小启动燃料量
     * @return 最小启动燃料量
     */
    public int getMinFuel() {
        return minFuel;
    }

    /**
     * 检查系统是否正在运行（非闲置状态）
     * @return 系统是否正在运行
     */
    public boolean isRunning() {
        return currentStage != Stage.IDLE;
    }

    /**
     * 检查系统是否处于平衡状态
     * @return 系统是否处于平衡状态
     */
    public boolean isBalanced() {
        return currentStage == Stage.BALANCED;
    }

    /**
     * 检查是否有足够的资源维持当前状态
     * @return 是否有足够的资源
     */
    public boolean hasSufficientResources() {
        return waterLevel >= minWater && fuelLevel >= minFuel;
    }

    // ===== 持久化接口 =====

    /**
     * 将数据保存到NBT
     * @param tag 要保存到的CompoundTag
     */
    public void writeToNBT(CompoundTag tag) {
        tag.putDouble("CurrentTorque", currentTorque);
        tag.putInt("CurrentStage", currentStage.getId());
        tag.putInt("WaterLevel", waterLevel);
        tag.putInt("FuelLevel", fuelLevel);
        tag.putBoolean("IsEnabled", isEnabled);

        clearDirty(); // 保存后清除脏标记
    }

    /**
     * 从NBT加载数据
     * @param tag 包含数据的CompoundTag
     */
    public void readFromNBT(CompoundTag tag) {
        if (tag.contains("CurrentTorque")) {
            currentTorque = tag.getDouble("CurrentTorque");
        }
        if (tag.contains("CurrentStage")) {
            currentStage = Stage.fromId(tag.getInt("CurrentStage"));
        }
        if (tag.contains("WaterLevel")) {
            waterLevel = tag.getInt("WaterLevel");
        }
        if (tag.contains("FuelLevel")) {
            fuelLevel = tag.getInt("FuelLevel");
        }
        if (tag.contains("IsEnabled")) {
            isEnabled = tag.getBoolean("IsEnabled");
        }

        clearDirty(); // 加载后清除脏标记
    }

    /**
     * 创建系统的深拷贝
     * @return 系统的深拷贝
     */
    public StagedSteamMechanism copy() {
        StagedSteamMechanism copy = new StagedSteamMechanism(
                maxTorque, risingRate, decliningRate,
                waterConsumption, fuelConsumption,
                minWater, minFuel
        );

        copy.currentStage = this.currentStage;
        copy.currentTorque = this.currentTorque;
        copy.waterLevel = this.waterLevel;
        copy.fuelLevel = this.fuelLevel;
        copy.isEnabled = this.isEnabled;

        return copy;
    }

    @Override
    public String toString() {
        return String.format(
                "StagedSteamMechanism{stage=%s, torque=%.1f/%.1f, water=%d/%d, fuel=%d/%d}",
                currentStage.getName(), currentTorque, maxTorque,
                waterLevel, minWater, fuelLevel, minFuel
        );
    }
}